package com.party.core.service.mall.biz;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.party.common.utils.LangUtils;
import com.party.common.utils.PartyCode;
import com.party.common.utils.StringUtils;
import com.party.core.api.order.IOrderDetailService;
import com.party.core.exception.BusinessException;
import com.party.core.model.BaseModel;
import com.party.core.model.mall.*;
import com.party.core.service.mall.*;
import com.party.core.utils.MyBeanUtils;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * 商城产品业务接口
 * Created by wei.li
 *
 * @date 2017/8/16 0016
 * @time 11:06
 */
@Service
public class ProductBizService implements IOrderDetailService {
    @Autowired
    private IMallProductService mallProductService;
    @Autowired
    private IMallGoodsSpecService mallGoodsSpecService;
    @Autowired
    private IMallSpecValueService mallSpecValueService;
    @Autowired
    private IMallOrderDetailService mallOrderDetailService;
    @Autowired
    private IMallShoppingCartService mallShoppingCartService;
    @Autowired
    private IMallGoodsService mallGoodsService;

    /**
     * 产品相关业务处理
     *
     * @param mallGoods 商品
     * @throws Exception
     */
    public void saveProductBiz(MallGoods mallGoods, List<MallProduct> products, List<MallSpec> specs) throws Exception {
        // 保存规格值
        List<String> newValueIds = this.saveSpecValue(specs);
        List<String> newProductIds = Lists.newArrayList();
        // 没有选择规格 默认生成一个产品
        if (CollectionUtils.isEmpty(specs)) {
            MallProduct product;
            if (products != null && products.size() > 0) {
                product = mallProductService.get(products.get(0).getId());
            } else {
                product = new MallProduct();
            }
            product.setSort(1);
            product.setPrice(Double.valueOf(mallGoods.getPrice()));
            product.setStock(mallGoods.getStock());
            product.setPic(mallGoods.getPic());
            product.setTradePrice(Double.valueOf(mallGoods.getTradePrice()));
            product.setCostPrice(Double.valueOf(mallGoods.getCostPrice()));
            product.setNumber(mallGoods.getNumber());

            if (StringUtils.isEmpty(product.getId())) {
                product.setRealStock(mallGoods.getStock());
                product.setSalesNum(0L);
                product.setGoodsId(mallGoods.getId());
                mallProductService.insert(product);
            } else {
                Long notPayCount = mallOrderDetailService.getNotPay(product.getId(), "");
                product.setRealStock(mallGoods.getStock() - notPayCount - product.getSalesNum());
                mallProductService.update(product);
            }
            newProductIds.add(product.getId());
        }
        // 选择规格，根据对应的规格生成产品
        if (CollectionUtils.isNotEmpty(specs)
                && CollectionUtils.isNotEmpty(products)) {
            for (MallProduct product : products) {
                if (StringUtils.isEmpty(product.getPic())) {
                    product.setPic(mallGoods.getPic());
                }
                if (StringUtils.isEmpty(product.getNumber())) {
                    product.setNumber(mallGoods.getNumber());
                }
                // 保存产品
                if (StringUtils.isEmpty(product.getId())) {
                    product.setGoodsId(mallGoods.getId());
                    product.setRealStock(product.getStock());
                    mallProductService.insert(product);
                } else {
                    MallProduct dbProduct = mallProductService.get(product.getId());
                    MyBeanUtils.copyBeanNotNull2Bean(product, dbProduct);
                    Long notPayCount = mallOrderDetailService.getNotPay(product.getId(), "");
                    dbProduct.setRealStock(product.getStock() - notPayCount - dbProduct.getSalesNum());
                    mallProductService.update(dbProduct);
                }
                newProductIds.add(product.getId());

                // 保存产品规格
                this.saveProductSpec(product.getSpecs(), product.getId(), mallGoods.getId());
            }
        }

        // 删除无用的产品及规格关系
        this.deleteProduct(mallGoods.getId(), newProductIds, newValueIds);
    }


    /**
     * 保存规格值
     *
     * @param specs 规格信息
     */
    public List<String> saveSpecValue(List<MallSpec> specs) {
        List<String> newValueIds = Lists.newArrayList();
        if (!CollectionUtils.isEmpty(specs)) {
            for (MallSpec spec : specs) {
                if (spec.getSpecValues() != null) {
                    for (MallSpecValue specValue : spec.getSpecValues()) {
                        if (StringUtils.isNotEmpty(specValue.getSpecId()) && StringUtils.isNotEmpty(specValue.getValue())) {
                            String specValueId;
                            MallSpecValue unique = mallSpecValueService.getUnique(new MallSpecValue(specValue.getSpecId(), specValue.getValue()));
                            if (unique == null) {
                                specValue.setId(null);
                                specValueId = mallSpecValueService.insert(specValue);
                            } else {
                                specValueId = unique.getId();
                            }
                            if (StringUtils.isEmpty(specValueId)) {
                                throw new BusinessException(100000, "保存规格时——获取规格值id异常");
                            }
                            newValueIds.add(specValueId);
                        }
                    }
                }
            }
        }
        return newValueIds;
    }

    /**
     * 保存产品规格
     *
     * @param specs     规格集合
     * @param productId 产品id
     * @param goodsId   商品id
     * @throws Exception
     */
    public void saveProductSpec(List<MallGoodsSpec> specs, String productId, String goodsId) throws Exception {
        // 保存产品规格
        if (!CollectionUtils.isEmpty(specs)) {
            for (MallGoodsSpec goodsSpec : specs) {
                MallSpecValue unique = mallSpecValueService.getUnique(new MallSpecValue(goodsSpec.getSpecId(), goodsSpec.getSpecValue()));
                if (unique == null) {
                    throw new BusinessException(100001, "保存产品规格关系表——规格值异常");
                }
                goodsSpec.setProductId(productId);
                goodsSpec.setGoodsId(goodsId);
                goodsSpec.setSpecValueId(unique.getId());
                MallGoodsSpec dbProductSpec = mallGoodsSpecService.getUnique(goodsSpec);
                if (dbProductSpec == null) {
                    mallGoodsSpecService.insert(goodsSpec);
                } else {
                    MyBeanUtils.copyBeanNotNull2Bean(goodsSpec, dbProductSpec);
                    mallGoodsSpecService.update(dbProductSpec);
                }
            }
        }
    }

    /**
     * 获取业务数据
     *
     * @param mallGoods 商品信息
     * @return 业务数据集合
     */
    public Map<String, Object> getBusiness(MallGoods mallGoods) {
        MallProduct mallProduct = new MallProduct();
        mallProduct.setGoodsId(mallGoods.getId());
        mallProduct.setDelFlag(BaseModel.DEL_FLAG_NORMAL);
        List<MallProduct> productList = mallProductService.list(mallProduct);

        // 规格
        List<MallSpecOutput> specValues = mallSpecValueService.getSpecValues(mallGoods.getId());
        for (MallSpecOutput specOutput : specValues) {
            specOutput.setSubModelId(specOutput.getSubIds().split(","));
            specOutput.setSubModelName(specOutput.getSubValues().split(","));
            if (specOutput.getSubPics() != null) {
                specOutput.setSubModelPic(specOutput.getSubPics().split(","));
            } else {
                specOutput.setSubModelPic(new String[specOutput.getSubModelId().length]);
            }
            specOutput.setSubModelSort(specOutput.getSubSorts().split(","));
        }

        Map<String, String> productSpecs = mallGoodsSpecService.getProductSpec(mallGoods.getId(), null);
        // 被刪除的产品里面的指标
        List<String> delModelList = Lists.newArrayList();
        List<MallProductOutput> productMaps = Lists.newArrayList();
        for (MallProduct p : productList) {
            MallProductOutput productOutput = new MallProductOutput();
            if (productSpecs != null) {
                String models = productSpecs.get(p.getId());
                productOutput.setModel(models);
//                if (p.getDelFlag().equals(BaseModel.DEL_FLAG_DELETE)) {
//                    delModelList.add(models);
//                }
            }
            productOutput.setProductId(p.getId());
            productOutput.setPrice(p.getPrice());
            productOutput.setStock(p.getStock());
            productOutput.setRealStock(p.getRealStock());
            productOutput.setSalesNum(p.getSalesNum());
            productOutput.setImgUrl(p.getPic());
            productOutput.setCostPrice(p.getCostPrice());
            productOutput.setTradePrice(p.getTradePrice());
            productOutput.setNumber(p.getNumber());
            productMaps.add(productOutput);
        }
        Map<String, Object> results = Maps.newHashMap();
        results.put("products", productMaps);
        results.put("delModelList", delModelList);
        results.put("speModels", specValues);
        return results;
    }

    /**
     * 如果产品已经有购买记录了，则逻辑删除；否则物理删除
     *
     * @param goodsId       商品id
     * @param newProductIds 新的产品id集合
     * @param newValueIds   新的产品值id集合
     */
    public void deleteProduct(String goodsId, List<String> newProductIds, List<String> newValueIds) {
        MallProduct mallProduct = new MallProduct();
        mallProduct.setGoodsId(goodsId);
//        mallProduct.setDelFlag(BaseModel.DEL_FLAG_NORMAL);
        List<MallProduct> oldProductList = mallProductService.list(mallProduct);
        if (oldProductList.size() > 0) {
            List<String> oldProductIds = LangUtils.transform(oldProductList, input -> input.getId());
            oldProductIds.removeAll(newProductIds);
            for (String productId : oldProductIds) {
                // 订单
                List<MallOrderDetail> orderDetails = mallOrderDetailService.findByProductId(productId);
                // 购物车
                List<MallShoppingCart> shoppingCarts = mallShoppingCartService.findByProductId(productId);
                if (orderDetails.size() == 0 && shoppingCarts.size() == 0) {
                    // 删除产品
                    mallProductService.delete(productId);
                    // 删除产品和规格的关系
                    this.deleteProductSpec(productId);
                } else {
                    mallProductService.deleteLogic(productId);
                }
            }
        }

        // 删除规格值
        this.deleteSpecValue(goodsId, newValueIds);
    }

    /**
     * 删除产品的规格关系
     *
     * @param productId 产品id
     */
    public void deleteProductSpec(String productId) {
        List<MallGoodsSpec> productSpecs = mallGoodsSpecService.findByProductId(productId);
        for (MallGoodsSpec productSpec : productSpecs) {
            mallGoodsSpecService.delete(productSpec.getId());
        }
    }

    /**
     * 如果规格值已经分配了产品，则逻辑删除；否则物理删除
     *
     * @param goodsId     商品id
     * @param newValueIds 新的规格值id集合
     */
    public void deleteSpecValue(String goodsId, List<String> newValueIds) {
        List<MallGoodsSpec> goodsSpecs = mallGoodsSpecService.findByGoodsId(goodsId);
        List<String> oldValueList = LangUtils.transform(goodsSpecs, input -> input.getSpecValueId());
        oldValueList.removeAll(newValueIds);
        Set<String> valueIds = new HashSet<String>(oldValueList);
        for (String specValueId : valueIds) {
            MallGoodsSpec goodsSpec = new MallGoodsSpec();
            goodsSpec.setSpecValueId(specValueId);
            goodsSpec.setGoodsId(goodsId);
            List<MallGoodsSpec> goodsSpecList = mallGoodsSpecService.list(goodsSpec);
            for (MallGoodsSpec mallGoodsSpec : goodsSpecList) {
                MallProduct product = mallProductService.get(mallGoodsSpec.getProductId());
                if (product == null) {
                    mallGoodsSpecService.delete(mallGoodsSpec.getId());
                } else if (product != null) {
                    if (BaseModel.DEL_FLAG_DELETE.equals(product.getDelFlag())) {
                        mallGoodsSpecService.deleteLogic(mallGoodsSpec.getId());
                    } else {
                        mallGoodsSpecService.delete(mallGoodsSpec.getId());
                    }
                }
            }
        }
    }

    /**
     * 复制产品
     *
     * @param oldGoodsId 旧的商品
     * @param newGoodsId 新的商品
     */
    public void copyProduct(String oldGoodsId, String newGoodsId) {
        MallProduct mallProduct = new MallProduct();
        mallProduct.setGoodsId(oldGoodsId);
        mallProduct.setDelFlag(BaseModel.DEL_FLAG_NORMAL);
        List<MallProduct> productList = mallProductService.list(mallProduct);
        for (MallProduct product : productList) {
            String oldProductId = product.getId();
            product.setId(null);
            product.setCreateDate(null);
            product.setUpdateDate(null);
            product.setGoodsId(newGoodsId);
            String newProductId = mallProductService.insert(product);
            this.copyProductSpec(oldProductId, newProductId, newGoodsId);
        }
    }

    /**
     * 复制产品规格
     *
     * @param oldProductId 旧的产品
     * @param newProductId 新的产品
     */
    private void copyProductSpec(String oldProductId, String newProductId, String newGoodsId) {
        List<MallGoodsSpec> productSpecs = mallGoodsSpecService.findByProductId(oldProductId);
        for (MallGoodsSpec productSpec : productSpecs) {
            productSpec.setId(null);
            productSpec.setProductId(newProductId);
            productSpec.setGoodsId(newGoodsId);
            mallGoodsSpecService.insert(productSpec);
        }
    }

    /**
     * 根据规格字符串转成集合
     *
     * @param model 规格
     * @return
     */
    public List<MallProductOutput.SpecObject> getSpecObjects(String model) {
        List<MallProductOutput.SpecObject> specObjects = Lists.newArrayList();
        if (StringUtils.isEmpty(model)) {
            return specObjects;
        }
        String[] values = model.split(";");
        for (String value : values) {
            String[] split = value.split(":");
            MallProductOutput.SpecObject specObject = new MallProductOutput.SpecObject();
            specObject.setName(split[0]);
            specObject.setValue(split[1]);
            specObjects.add(specObject);
        }
        return specObjects;
    }

    /**
     * 付款 增加销量
     *
     * @param productId 产品id
     * @param quantity  购买数量
     */
    public void payUpdateSalesNum(String productId, Integer quantity) {
        MallProduct product = mallProductService.get(productId);
        Long pSalesNum = product.getSalesNum() + quantity;
        product.setSalesNum(pSalesNum);
        mallProductService.update(product);

        MallGoods mallGoods = mallGoodsService.get(product.getGoodsId());
        Long gSalesNum = mallGoods.getSalesNum() + quantity;
        mallGoods.setSalesNum(gSalesNum);
        mallGoodsService.update(mallGoods);
    }

    /**
     * 取消 增加库存
     *
     * @param productId 产品id
     * @param quantity  购买数量
     */
    public void cancelUpdateStock(String productId, Integer quantity) {
        MallProduct product = mallProductService.get(productId);
        Long pStock = product.getRealStock() + quantity;
        if (pStock > product.getStock()) {
            pStock = product.getStock();
        }
        product.setRealStock(pStock);
        mallProductService.update(product);

        // 如果产品是正常的，商品数量加回；如果产品已被删除，不用加回。
        if (product.getDelFlag().equals(BaseModel.DEL_FLAG_NORMAL)) {
            MallGoods mallGoods = mallGoodsService.get(product.getGoodsId());
            Long gStock = mallGoods.getRealStock() + quantity;
            if (gStock > mallGoods.getStock()) {
                gStock = mallGoods.getStock();
            }
            if (gStock > 0L && mallGoods.getStatus().equals(MallGoods.STATUS_SELL_OUT)) {
                mallGoods.setStatus(MallGoods.STATUS_UP);
            }
            mallGoods.setRealStock(gStock);
            mallGoodsService.update(mallGoods);
        }
    }

    /**
     * 下单 减少库存
     *
     * @param productId 产品id
     * @param quantity  购买数量
     */
    public void buyOrderUpdateStock(String productId, Integer quantity) {
        MallProduct product = mallProductService.get(productId);
        Long pStock = product.getRealStock() - quantity;
        if (pStock < 0) {
            pStock = 0L;
        }
        product.setRealStock(pStock);
        mallProductService.update(product);

        MallGoods mallGoods = mallGoodsService.get(product.getGoodsId());
        Long gStock = mallGoods.getRealStock() - quantity;
        if (gStock < 0) {
            gStock = 0L;
        }
        if (gStock == 0L) {
            mallGoods.setStatus(MallGoods.STATUS_SELL_OUT);
        }
        mallGoods.setRealStock(gStock);
        mallGoodsService.update(mallGoods);
    }

    /**
     * 退款 减少销量 增加库存
     *
     * @param productId 产品编号
     * @param quantity  购买数量
     */
    public void refundUpdateSalesNumAndStock(String productId, Integer quantity) {
        MallProduct product = mallProductService.get(productId);
        Long pSalesNum = product.getSalesNum() - quantity;
        if (pSalesNum < 0) {
            pSalesNum = 0L;
        }
        product.setSalesNum(pSalesNum);
        Long pStock = product.getRealStock() + quantity;
        if (pStock > product.getStock()) {
            pStock = product.getStock();
        }
        product.setRealStock(pStock);
        mallProductService.update(product);

        MallGoods mallGoods = mallGoodsService.get(product.getGoodsId());
        Long gSalesNum = mallGoods.getSalesNum() - quantity;
        if (gSalesNum < 0) {
            gSalesNum = 0L;
        }
        mallGoods.setSalesNum(gSalesNum);
        // 如果产品是正常的，商品数量加回；如果产品已被删除，不用加回。
        if (product.getDelFlag().equals(BaseModel.DEL_FLAG_NORMAL)) {
            Long gStock = mallGoods.getRealStock() + quantity;
            if (gStock > mallGoods.getStock()) {
                gStock = mallGoods.getStock();
            }
            if (gStock > 0L && mallGoods.getStatus().equals(MallGoods.STATUS_SELL_OUT)) {
                mallGoods.setStatus(MallGoods.STATUS_UP);
            }
            mallGoods.setRealStock(gStock);
        }
        mallGoodsService.update(mallGoods);
    }

    /**
     * 取消订单 更改订单状态 释放库存
     *
     * @param orderFormId
     * @throws Exception
     */
    public void releaseInventory(String orderFormId) {
        MallOrderOutputPay orderOutputPay = mallOrderDetailService.findByOrderId(orderFormId);
        for (MallOrderOutputParent orderOutput : orderOutputPay.getChildrens()) {
            if (orderOutput == null) {
                throw new BusinessException(PartyCode.IS_NO_DATA, "订单为空");
            }
            if (!orderOutput.getStatus().equals(MallOrderDetailStatus.STATUS_NOT_PAY.getCode())) {
                throw new BusinessException(PartyCode.PAYMENT_STATUS_ERROR, "订单状态异常");
            }

            this.cancelOrder(orderOutput);
        }
    }

    public void deleteByGoods(String goodsId) {
        List<MallProduct> mallProducts = mallProductService.findByGoodsId(goodsId);
        for (MallProduct mallProduct : mallProducts) {
            // 购物车
            mallShoppingCartService.deleteByProductId(mallProduct.getId());
        }
        mallGoodsSpecService.deleteByGoodsId(goodsId);
        mallProductService.deleteByGoodsId(goodsId);
    }

    /**
     * 取消订单
     *
     * @param orderOutput 订单数据
     */
    public void cancelOrder(MallOrderOutputParent orderOutput) {
        MallOrderDetail pOut = mallOrderDetailService.get(orderOutput.getId());
        pOut.setStatus(MallOrderDetailStatus.STATUS_CLOSED.getCode());
        mallOrderDetailService.update(pOut);

        for (MallOrderOutputChild childOut : orderOutput.getChildrens()) {
            MallOrderDetail cOut = mallOrderDetailService.get(childOut.getId());
            cOut.setStatus(MallOrderDetailStatus.STATUS_CLOSED.getCode());
            mallOrderDetailService.update(cOut);

            this.cancelUpdateStock(cOut.getProductId(), cOut.getQuantity());
        }
    }

    @Override
    public void releaseStock(String orderId) {
        this.releaseInventory(orderId);
    }
}
